package megrez.keycloak.providers.event;

import java.io.IOException;

import org.eclipse.paho.client.mqttv3.MqttException;
import org.keycloak.events.Event;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventListenerTransaction;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.models.KeycloakSession;

import lombok.extern.slf4j.Slf4j;
import megrez.keycloak.common.KeycloakAdminEvent;
import megrez.keycloak.common.KeycloakEvent;
import megrez.keycloak.providers.mqtt.MqttService;
import megrez.keycloak.providers.mqtt.MqttUtils;

/**
 * 事件监听
 * 
 * @author Lucky Yang
 * @since 2.6.9
 */
@Slf4j
public class MqttEventListenerProvider implements EventListenerProvider {
    private final KeycloakSession session;

    private final EventListenerTransaction tx = new EventListenerTransaction(this::publishAdminEvent,
            this::publishEvent);

    public MqttEventListenerProvider(KeycloakSession session) {
        this.session = session;
        session.getTransactionManager().enlistAfterCompletion(tx);
    }

    @Override
    public void close() {
        // 不需要实现
    }

    @Override
    public void onEvent(Event event) {
        tx.addEvent(event);
    }

    @Override
    public void onEvent(AdminEvent event, boolean includeRepresentation) {
        tx.addAdminEvent(event, includeRepresentation);
    }

    private void publishEvent(Event event) {
        final String topic = EventUtils.getTopic(event);
        final KeycloakEvent message = EventUtils.of(event);
        MqttService client = session.getProvider(MqttService.class);
        sendToMqtt(client, topic, message);
    }

    private void publishAdminEvent(AdminEvent event, Boolean includeRepresentation) {
        final String topic = EventUtils.getTopic(event);
        final KeycloakAdminEvent message = EventUtils.of(event);
        MqttService client = session.getProvider(MqttService.class);
        sendToMqtt(client, topic, message);
    }

    private void sendToMqtt(MqttService client, String topic, Object message) {
        try {
            if (!client.isConnected()) {
                client.reconnect();
            }
            client.publish(topic, MqttUtils.buildJsonMqttMessage(message, 2, true));
        } catch (MqttException | IOException e) {
            log.error("Send message to MQTT server exception", e);
        }

    }
}
